package de.gbeine.java.depview.graph;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;

import lombok.extern.slf4j.Slf4j;

import de.gbeine.java.depview.model.Element;

/**
 *
 */
@Slf4j
public final class Filter {

    /**
     * The set of compiled patterns to filter.
     */
    private final Set<Pattern> patterns = new HashSet<Pattern>();

    /**
     * The set of strings to be filtered.
     */
    private final Set<String> filter;

    /**
     *
     * @param pFilter
     */
    public Filter(final Set<String> pFilter) {
        this.filter = pFilter;
        this.compileFilters();
    }

    /**
     * Add a string to the filter.
     * @param pFilter The string to add
     */
    public void addFilter(final String pFilter) {
        this.filter.add(pFilter);
        this.patterns.add(Pattern.compile(pFilter));
    }

    /**
     * Remove a string from filter.
     * @param pFilter The string to remove
     */
    public void removeFilter(final String pFilter) {
        this.filter.remove(pFilter);
        this.compileFilters();
    }

    /**
     * The filter strings as a set.
     * @return An unmodifiable set of strings
     */
    public Set<String> getFilter() {
        return Collections.unmodifiableSet(this.filter);
    }

    /**
     * Test if an element is filtered.
     * @param pElement The element to test for
     * @return True if the element is filtered, otherwise false
     */
    public boolean isFiltered(final Element pElement) {
        // This is a little bit ugly...
        // Unfortunately there are some files with null values in package names
        // The default package should be dropped out from Java
        boolean matched = null == pElement.getName();
        if (!matched) {
            for (final Pattern pattern : this.patterns) {
                matched |= pattern.matcher(pElement.getName()).matches();
            }
        }
        return matched;
    }

    /**
     * Rebuild the filter set.
     */
    private void compileFilters() {
        this.patterns.clear();
        for (final String patternString : this.filter) {
            this.patterns.add(Pattern.compile(patternString));
        }

    }
}
